package com.zktravel.service.cart;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.zktravel.service.BaseServiceImpl;
import com.zktravel.service.message.WxMsgService;
import com.zktravel.service.order.CusCouponService;
import com.zktravel.util.StringConcatUtils;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import com.zktravel.constants.CommonConstant;
import com.zktravel.core.exception.VisibleException;
import com.zktravel.core.vo.ObjectResult;
import com.zktravel.enums.CodeEnum;
import com.zktravel.mapper.CartMapper;
import com.zktravel.mapper.TaProductMapper;
import com.zktravel.model.dto.cart.CartDTO;
import com.zktravel.model.dto.user.UserInfo;
import com.zktravel.model.po.Cart;
import com.zktravel.model.po.CusCoupon;
import com.zktravel.model.vo.cart.CartExtVO;
import com.zktravel.model.vo.cart.CartVO;
import com.zktravel.model.vo.product.TaProductVO;

@Service
public class CartServiceImpl extends BaseServiceImpl implements CartService {

    @Resource
    private CartMapper cartMapper;
    @Resource
    private TaProductMapper taProductMapper;
    @Resource
    private CusCouponService cusCouponService;
    @Resource
    private WxMsgService wxMsgService;

    //添加购物车
    @Override
    public Integer add(CartDTO dto, Long shopId, Long userId, Integer platformType) {
        Long tpid = dto.getProductId();
        //查询商品是否存在
        TaProductVO taProductVO = this.taProductMapper.selectById(tpid, shopId);
        if (null == taProductVO) {
            throw new VisibleException(CodeEnum.PRODUCT_NOT_EXIST);
        }
        Long ppid = taProductVO.getProductId();
        Integer stockNum = taProductVO.getStockNum();

        //根据用户id，店铺id,商品id获取记录，如果为空添加1条，如果已存在，加num
        Cart cart = new Cart();
        cart.setTpid(tpid);
        cart.setShopId(shopId);
        cart.setUserId(userId);
        cart.setPlatformType(platformType);
        cart.setIsDeleted(CommonConstant.NO);

        Cart prod = cartMapper.getCartInfo(cart);

        if (null == prod) {
            cart.setNum(dto.getNum());
            this.checkStockNum(stockNum, cart.getNum());
            cart.setStatus(CommonConstant.AVAILABLE);
            cart.setCreateUserId(userId);
            cart.setPpid(ppid);
            cartMapper.insert(cart);

            String mpName = StringConcatUtils.concatString("", taProductVO.getName(), CommonConstant.CONCAT_LENGTH_30);
            //异步发送消息
            wxMsgService.sendCartMsgToTailor(shopId, userId, mpName, tpid);
        } else {
            Cart updateCart = new Cart();
            updateCart.setNum(dto.getNum() + prod.getNum());
            this.checkStockNum(stockNum, updateCart.getNum());
            updateCart.setId(prod.getId());

            cartMapper.updateNumByProduct(updateCart);
        }

        return getCartNum(userId, shopId, platformType);
    }

    private void checkStockNum(Integer stockNum, Integer cartNum) {
        if (stockNum.compareTo(cartNum) < 0) {
            throw new VisibleException(CodeEnum.PRODUCT_STOCK_NUM_LT_0);
        }
    }

    //获取购物车数量
    @Override
    public Integer getCartNum(Long userId, Long shopId, Integer platformType) {
        return cartMapper.getCartNum(userId, shopId, platformType);
    }

    //删除
    @Override
    public Integer deleteWithTx(CartDTO dto) {
        this.cartMapper.deleteByIds(dto);
        return getCartNum(dto.getUid(), dto.getSid(), dto.getPlatformType());
    }

    //更改购物车商品数量
    @Override
    public CartVO updateWithTx(CartDTO dto, Long shopId, Integer platformType) {
        //如果数量大于库存数量，则判断与购物车数量大小比较，如果大于，则不变，如果小于，则更改
        //根据id获取商品信息
        dto.setPlatformType(platformType);
        CartVO vo = this.cartMapper.getCartProductInfo(dto);
        if (null == vo) {
            throw new VisibleException(CodeEnum.PRODUCT_NOT_EXIST);
        }
        //根据vo获取状态
        TaProductVO taProductVO = this.taProductMapper.selectById(vo.getProductId(), shopId);

        if (null == taProductVO) {
            throw new VisibleException(CodeEnum.PRODUCT_NOT_EXIST);
        }
        vo.setStatus(taProductVO.getStatus());

        if ((dto.getNum() > vo.getStockNum()) && (dto.getNum() > vo.getNum())) {
            return vo;
        }

        this.cartMapper.updateNum(dto);
        vo.setNum(dto.getNum());

        if (CommonConstant.PLATFORM_TYPE_C.equals(platformType)) {
            vo.setMarketPrice(null);
            vo.setMarketPriceVip(null);
        }

        return vo;
    }

    @Override
    public ObjectResult<CartExtVO> listShop(Long userId, Long shopId) {
        CartDTO cDto = new CartDTO();
        cDto.setUid(userId);
        cDto.setSid(shopId);
        cDto.setPlatformType(CommonConstant.PLATFORM_TYPE_B);

        List<CartVO> list = this.cartMapper.listShop(cDto);
        BigDecimal totalAmt = BigDecimal.ZERO;
        BigDecimal leaveAmt = BigDecimal.ZERO;

        if (CollectionUtils.isNotEmpty(list)) {
            // 如果是vip，优先使用vip价格，如果没有vip价，使用正常价
            for (CartVO vo : list) {
                BigDecimal price = vo.getTotalMarketPrice();
                if (this.getUser(userId).isVip() && null != vo.getTotalMarketPriceVip()
                        && vo.getTotalMarketPriceVip().compareTo(BigDecimal.ZERO) > 0) {
                    leaveAmt = leaveAmt.add(vo.getTotalMarketPrice().subtract(vo.getTotalMarketPriceVip()));
                    price = vo.getTotalMarketPriceVip();
                }
                totalAmt = totalAmt.add(price);
            }
        }

        CartExtVO cart = new CartExtVO();
        cart.setCartList(list);
        cart.setLeaveAmt(leaveAmt);
        cart.setTotalAmt(totalAmt);

        return ObjectResult.ok(cart);
    }

    @Override
    public ObjectResult<CartExtVO> listShopClient(Long userId, Long shopId) {
        CartDTO cDto = new CartDTO();
        cDto.setUid(userId);
        cDto.setSid(shopId);
        cDto.setPlatformType(CommonConstant.PLATFORM_TYPE_C);

        List<CartVO> list = this.cartMapper.listShop(cDto);

        BigDecimal totalAmt = BigDecimal.ZERO;
        BigDecimal leaveAmt = BigDecimal.ZERO;
       
        if (CollectionUtils.isNotEmpty(list)) {
            //获取店主的isvip
        	Boolean isVip = false;
        	UserInfo userInfo = this.getUserInfoByShopId(shopId);
        	if(null != userInfo){
        		isVip = userInfo.isVip();
        	}
            
            //获取优惠券
            List<Long> tpidList = list.stream().map(CartVO::getProductId).collect(Collectors.toList());
            Map<Long, CusCoupon> couponMap = cusCouponService.getMapByTpids(tpidList, userId, shopId);

            for (CartVO vo : list) {
               
            	//成本价
                if (isVip && null != vo.getMarketPriceVip()) {
                    vo.setMarPrice(vo.getMarketPriceVip());
                } else {
                    vo.setMarPrice(vo.getMarketPrice());
                }
                
                BigDecimal price = vo.getSellPrice().compareTo(vo.getCounterPrice()) >= 0 ? vo.getSellPrice() : vo.getCounterPrice();
                Integer num = (null != vo.getNum()) ? vo.getNum() : 0;
                BigDecimal totalPrice = price.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
                CusCoupon coupon = couponMap.get(vo.getProductId());
               
                // 优惠券数据
                BigDecimal profitUnitAmt = price.subtract(vo.getMarPrice());
                if (null != coupon && coupon.getAmt().compareTo(BigDecimal.ZERO) > 0 &&
                		profitUnitAmt.subtract(coupon.getAmt()).compareTo(BigDecimal.ZERO) > 0) {
                    
                	vo.setCouponAmt(coupon.getAmt());
                    leaveAmt = leaveAmt.add(coupon.getAmt().multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP));
                    // 前端需要剩余的秒数 （毫秒）
                    vo.setExpireTime((long) coupon.getExpireTime() * 1000 - System.currentTimeMillis());
                    
                    totalPrice = totalPrice.subtract(leaveAmt);
                }
                
                // c端购物车数据需要过滤 成本数据不能返回
                vo.setMarketPrice(null);
                vo.setMarketPriceVip(null);
                
                totalAmt = totalAmt.add(totalPrice);
            }
        }

        CartExtVO cart = new CartExtVO();
        cart.setCartList(list);
        cart.setLeaveAmt(leaveAmt);
        cart.setTotalAmt(totalAmt);

        return ObjectResult.ok(cart);
    }
}
